/**
 * 
 */
package baduga.server;

import baduga.core.Core_Exception;

/**
 * @author Janek
 *
 */
public class Table {
	
	
	/**
	 * Ustawienia stołu
	 * 0 - minimalna ilość graczy
	 * 1 - aktualna ilość graczy
	 * 2 - min małą w ciemno
	 * 3 - max mała w ciemno
	 * 4 - min duża w ciemno
	 * 5 - max duża w ciemno
	 * 6 - czas ruchu gracza
	 * 7 - aktualna ilość obserwatorów
	 * 8 - nrRundy
	 */
	private int settingsTable[] = new int[10];
	
	/**
	 * Zwraca informacje o stole
	 * 0 - wolny
	 * 1 - zapełniony
	 * 2 - gra w toku
	 */
	private int status = 0;
	
	/**
	 * Parametry tekstowe stołu
	 * 0 - nazwa
	 * 1 - opis
	 * 2 - hasło
	 */
	private String textData[] = new String[3];
	
	/** Tablica gracz0y (Zawiera ich id) */
	private String[] tabPlayers;
	
	/** Tablica obserwatorów (Zawiera ich id) */
	private String[] tabObservers;
	
	/** Identyfikator Twórcy/Administratora stołu */
	private String adminID;
	
	/** Zawiera Talie graczy 
	 * 
	 *  nData - Dane numeryczne obowiązuje numeracja
	 * 0 - minimalna ilość graczy
	 * 1 - min małą w ciemno
	 * 2 - max mała w ciemno
	 * 3 - min duża w ciemno
	 * 4 - max duża w ciemno
	 * 5 - czas ruchu gracza
	 * 6 - aktualna ilość obserwatorów
	 * 7 - Max il. graczy
	 * 8 - Max il. obserwatorów
	 *  
	 *  tData - Dane tekstowe (Obowiązuje numeracja wg. textData)
	 *  
	 * 
	 * */
	Table(int[] nData, String[] tData, String adminID)
	{
		/*  Parametry przepisania */
		int[] keys = {0, 2, 3, 4, 5, 6, 7};
		
		/*  Przepisanie tablicy intów */
		for(int i = 0; i < keys.length; i++)
			settingsTable[ keys[i] ] = nData[i];
		
		
	    //Ustawienie ilości graczy i obserwatorów
	    settingsTable[1] = 1;
	    settingsTable[7] = 0;
	    
	    //Ustawienie nr. Rundy
	    settingsTable[8] = 0;
	    
	    /** Ustalenie admina/Twórcy */
	    this.adminID = adminID;
				
		
		textData = tData;
		
		/** Inicjalizacja tabeli ID graczy oraz ID obserwatorów*/
		this.tabPlayers = new String[  nData[7] ];
		this.tabObservers = new String[ nData[8] ];
		
		
	}


	
	
	/**
	 * Sprawdza czy stół nie jest pełny w wariance dla obserwatorów lub
	 * 
	 * @param type określa czy sprawdzamy graczy czy obserwatorów. 0 - obserwatorzy, 1 - player
	 * @return
	 */
	public boolean isNotFull(final int type)
	{
		boolean opStatus;
		
		if(type == 1)
		{
			/* Sprawdza czy ilośc aktualna graczy + 1 nie przekracza limitu*/
			if(settingsTable[1] + 1 <= this.tabPlayers.length)
			{
				opStatus = true;
			}
			else
			{
				//TODO: Rzucamy komunikat o zbyt dużej ilości ludzi
				opStatus = false;
			}
				
		}
		else
		{
			if(settingsTable[8] + 1 <= settingsTable[7])
			{
				opStatus = true;
			}
			else
			{
				//TODO: Rzucamy komunikat o zbyt dużej ilości ludzi
				opStatus = false;
			}
				
		}
		
		
		return opStatus;
		
	}
	
	
	@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
	/**
	 * Funkcja zmienia status gracza w stole z obserwatora na 
	 * 
	 * 0 - obserwatorzy, 1 - player
	 * 
	 * @param playerID
	 * @param type
	 * @throws Core_Exception
	 */
	private void sitAs(int type, final String playerID) throws Core_Exception
	{
		/** Konfiguracja dla typu
		 * 0  - Kody komunikatów błędów
		 * 1  - id_pozycji w settings odnośnie ilości graczy / obs
		 * 
		 **/

		int tmpSets[][];
		
		if(type == 0)
		{
			
			tmpSets = new int[][] {
					new int[] {0x0000, 0x0000},
					new int[] {7}
			};
			
		}
		else
		{
			
			tmpSets = new int[][] {
					new int[] {0x0000, 0x0000},
					new int[] {1}
			};
			
		}
		
		
		
		
		/** Czy Wolny identyfikator gracza*/
		if(isNotFull(type))
		{
			//Pre rezerwacja miejsca
			settingsTable[ tmpSets[1][1] ] += 1;
			
			int nr = findFreeID(type);
			
			if(nr != -1)
			{
				this.tabPlayers[nr] = playerID;
				
				
				//TODO: SetPlayerStatus
				
				type = type == 1 ? 0 : 1;
				
				//Usuwamy gracza z listy obserwatorów
				unSitAs(type, playerID);
			}
			else
			{
				//Cofanie rezerwacji
				settingsTable[ tmpSets[1][1] ] -= 1;
				
				//TODO: Error o braku wolnych miejsc.
				//tmpSets[0][1] 
			}
			
			
		}
		else
		{
			//TODO: Error o braku wolnych miejsc.
			//tmpSets[0][0] 
		}
	}
	
	
	@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
	/**
	 * 
	 * Jeżeli funkcja zwróci -1 oznacza brak wolnych slotów
	 * 
	 * @param type
	 * @return
	 */
	private int findFreeID(final int type)
	{
		int rNum = -1; 
		int i = 0;;
		
		String[] tab;
		
		
		if(type == 0)
		{
			tab = this.tabObservers;
		}
		else
		{
			tab = this.tabPlayers;
		}
		
		
		while(i < tab.length)
		{
			if(tab[i].isEmpty())
			{
				rNum = i;
				break;
			}
			
			i++;
		}
		
		
		
		return rNum;
	}
	
	
	
	
	
	
	
	@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
	/**
	 * Funkcja zajmuje się usuwanie graczy z danej grupy obserwatorów  / graczy;
	 * 
	 *  TYP:  0 - obserwatorzy, 1 - player
	 * 
	 * @param type
	 * @param playerID
	 * @throws Core_Exception
	 */
	private void unSitAs(final int type, final String playerID) throws Core_Exception
	{
		int tTab,
			errorID;
		
		int nr = -1,
			i = 1;
		
		String tmpTab[];
		
		if(type == 0)
		{
			tTab = 7;
			tmpTab = this.tabObservers;
			errorID = 0x000;
		}
		else
		{
			tTab = 1;
			tmpTab = this.tabPlayers;
			errorID = 0x000;
		}
		

		
		while(i < tmpTab.length)
		{
			if(tmpTab[i].equals(playerID))
			{
				//Wyzerowanie
				tmpTab[i] = "";
				nr = i;
				break;
			}
			
			++i;
		}
		
		
		
		
		
		//Zmniejszenie ilości aktualnie graczy
		settingsTable[tTab] -= 1;
		
		
		if(nr == -1)
		{
			//TODO:Rzucić wyjątkiem
			//errorID
		}
		
	}
	
	
	
	/**
	 * Obsługuje wyjście gracza.
	 * 
	 * @param PlayerId
	 */
	public void rageQuit(String playerId)
	{
		//TODO: SetPlayerStatus
		//TODO: SetPlayerStatus
	}
	
	
	
	/**
	 * 
	 * Funkcja sprawdza poprawność danych wejściowych
	 * 
	 */
	public static void validateInput()
	{
		
	}
	
	
	
	
	//------------------ [setters] - #START ------------------
	
	
	
	/**
	 * Ustawia nrAktualnej rundy
	 * @param nrRundy
	 */
	public void setRunda(final int nrRundy)
	{
		this.settingsTable[8] = nrRundy;
	}
	
	

	
	//------------------ [setters] - #END ------------------
	
	
	
	//------------------ [getters] - #START ------------------
	
	/**
	 * Zwraca nrAktualnej rundy
	 * @return
	 */
	public int getRunda()
	{
		return this.settingsTable[8];
	}
	
	/**
	 * Zwaraca informacje o statusie stołu
	 * @return
	 */
	public int getStatus()
	{
		return this.status;
	}
	
	
	//------------------ [getters] - #END ------------------
	
	
	//------------------ [ADVgetters] - #START ------------------
	//------------------ [ADVgetters] - #END ------------------

	
	
	
}
